﻿using LYR_RPA.models.entity;
using LYR_RPA.models.events;
using LYR_RPA.Properties;
using LYR_RPA.utils;
using System;
using System.Threading.Tasks;
using WebSocketSharp;

namespace LYR_RPA.service
{
    public class WebSocketClient
    {
        private static WebSocketClient instance;
        private WebSocket webSocket; // WebSocket 实例
        private bool isConnected = false; // 是否成功连接到 WebSocket 服务器
        private static int reconnectInterval = 1000; // 重新连接时的间隔时间，默认为 1000ms
        private readonly int maxReconnectInterval = 60000; // 重新连接时的最大间隔时，默认为 60000ms

        private string address;
        private string port;

        // 定义与 WebSocket 事件关联的事件处理程序
        public static event EventHandler<Result<object>> MessageReceived; // 当接收到消息时发生

        private MessageHandle messageHandle;

        private WebSocketClient() { }

        public static WebSocketClient Instance => instance ?? (instance = new WebSocketClient());


        // 连接 WebSocket 服务器
        public async Task Connect()
        {
            await Task.Run(( ) =>
            {
                
                // 关闭之前的连接
                CloseWebSocket();
                // 读取新的地址和端口
                if (!string.IsNullOrEmpty(Settings.Default.ServerAddress))
                {
                    address = Settings.Default.ServerAddress;
                }
                if (!string.IsNullOrEmpty(Settings.Default.Port))
                {
                    port = Settings.Default.Port;
                }
                // 构建新的 WebSocket 地址
                var uriBuilder = new UriBuilder($"ws://{address}:{port}/jshERP-boot/websocket")//ws://localhost:8093/jshERP-boot/websocket?ip=127.0.0.1&dept=生产&identification=
                {
                    Query = $"identification="+(string.IsNullOrEmpty(Settings.Default.ID)?"":Settings.Default.ID)
                };

                // 创建新的 WebSocket 实例
                Console.WriteLine(uriBuilder.ToString());
                webSocket = new WebSocket(uriBuilder.Uri.ToString());

                // 将 WebSocket 事件与事件处理程序关联
                webSocket.OnMessage += OnWebSocketMessage;
                webSocket.OnClose += OnWebSocketCloseAsync;
                webSocket.OnOpen += OnWebSocketOpen;
                webSocket.Connect();
            });
        }

        private void OnWebSocketOpen(object sender, EventArgs e)
        {
            reconnectInterval=1000;
            isConnected=true;
            Console.WriteLine("连接成功");
        }

        // 发送消息到 WebSocket 服务器
        public void SendMessage(string message)
        {
            if (IsWebSocketConnected())
            {
                webSocket.Send(message);
            }
        }

        // 关闭 WebSocket 连接
        public void Close()
        {
            CloseWebSocket();
        }

        // 返回当前是否已连接到 WebSocket 服务器
        public bool IsConnected() => IsWebSocketConnected();

        // WebSocket 关闭时的处理
        private async void OnWebSocketCloseAsync(object sender, CloseEventArgs e)
        {
            isConnected = false;
            Console.WriteLine($"正在重连：" + reconnectInterval);
            reconnectInterval = Math.Min(reconnectInterval * 2, maxReconnectInterval);
            
            await Task.Delay(reconnectInterval);
            
            await Connect();
        }

        // 处理接收到的消息
        private void OnWebSocketMessage(object sender, MessageEventArgs e)
        {
            string message = e.Data;

            if (!string.IsNullOrEmpty(message.Trim()))
            {
                Console.WriteLine($"{message}");
                Result<object> result = JSONUtils.StringToObject<Result<object>>(e.Data);
                if (messageHandle == null)
                {
                    messageHandle = new MessageHandle();
                }
                // 将消息发送到订阅事件中
                MessageReceived?.Invoke(this, result);
            }
        }

        // 判断 WebSocket 是否连接
        private bool IsWebSocketConnected()
        {
            return webSocket != null && webSocket.IsAlive;
        }

        // 关闭 WebSocket 连接
        private void CloseWebSocket()
        {
            if (IsWebSocketConnected())
            {
                webSocket.Close();
                isConnected = false;
            }
        }
    }
}
